package me.zhengjie.kwService.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import me.zhengjie.constant.KwConstant;
import me.zhengjie.domain.KwMasterTearcher;
import me.zhengjie.kwService.PhoneTearcherService;
import me.zhengjie.mapper.*;
import me.zhengjie.pojo.dto.PageDto;
import me.zhengjie.pojo.entity.*;
import me.zhengjie.pojo.vo.ExamDetailVo;
import me.zhengjie.util.AssertUtils;
import me.zhengjie.util.BaseResponse;
import me.zhengjie.util.RedisUtils;
import me.zhengjie.util.ruoyiexcel.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author Long
 * @date 2021/7/6 15:08
 */
@Service
public class PhoneTearcherServiceImpl implements PhoneTearcherService {

    @Autowired
    private PublicExamMapper publicExamMapper;
    @Autowired
    private ExamMapper examMapper;
    @Autowired
    private ExamTeacherMapper examTeacherMapper;
    @Autowired
    private ExamRoomMapper examRoomMapper;
    @Autowired
    private ExamStudentMapper examStudentMapper;
    @Autowired
    private OccupyMapper occupyMapper;

    @Override
    public IPage<PublicExam> findPublicExam(Integer current, Integer size) {
        AssertUtils.isNotNull(current, "当前页码不可为空");
        AssertUtils.isNotNull(size, "当前页码条数不可为空");
        IPage<PublicExam> page = new Page<>(current, size);
        page = publicExamMapper.selectPage(page, null);
        return page;
    }

    @Override
    public PublicExam findOnePublicExam(Integer id) {
        AssertUtils.isNotNull(id, "考试公开信息id不可为空");
        PublicExam publicExam = publicExamMapper.selectById(id);
        return publicExam;
    }

    @Override
    public IPage<Exam> findExam(Integer current, Integer size, HttpServletRequest request) {
        AssertUtils.isNotNull(current, "当前页码不可为空");
        AssertUtils.isNotNull(size, "当前页码条数不可为空");
        IPage<Exam> page = new Page<>(current, size);
        /*从登录信息中获取老师的id*/
        MasterTearcher masterTearcher = RedisUtils.INSTANCE.getLoginInfo(request.getHeader(KwConstant.USERTOKEN), MasterTearcher.class);
        AssertUtils.isNotNull(masterTearcher, "登录信息为空");
        Integer id = masterTearcher.getId();
        if (id != null) {
            page = examMapper.findTearcherExam(page, id);
            return page;
        }
        return null;
    }

    @Override
    public ExamDetailVo findExamDetail(Integer id, HttpServletRequest request) {
        AssertUtils.isNotNull(id, "考试id为空");
        Exam exam = examMapper.selectById(id);
        ExamDetailVo vo = new ExamDetailVo();
        vo.setExam(exam);
        MasterTearcher masterTearcher = RedisUtils.INSTANCE.getLoginInfo(request.getHeader(KwConstant.USERTOKEN), MasterTearcher.class);
        AssertUtils.isNotNull(masterTearcher, "登录信息为空");

        /*查询出该考试id下的所有监考老师*/
        QueryWrapper<ExamTeacher> wrapper = new QueryWrapper<>();
        wrapper.eq("exam_id", id)
                .eq("identity", "0");
        List<ExamTeacher> examTeachers = examTeacherMapper.selectList(wrapper);
        if (!examTeachers.isEmpty()) {
            /*找到所有监考老师中当前的登录用户监考老师*/
            for (ExamTeacher examTeacher : examTeachers) {
                if (Objects.equals(masterTearcher.getId(), examTeacher.getTeacherId())) {
                    /*如果当前登录老师有考场，那么查出相应的考场*/
                    Integer examRoomId = examTeacher.getExamRoomId();
                    if (examRoomId != null) {
                        ExamRoom examRoom = examRoomMapper.selectById(examRoomId);
                        AssertUtils.isNotNull(examRoom, "考场不存在");
                        vo.setExamRoom(examRoom);
                    }
                }
            }
        }
        /*如果该监考老师有监考的考场，取出考场id，查出所有在此考场的监考教师返回*/
        LinkedList<ExamTeacher> list = new LinkedList<>();
        if (vo.getExamRoom() != null) {
            Integer examRommId = vo.getExamRoom().getId();
            if (!examTeachers.isEmpty()) {
                for (ExamTeacher examTeacher : examTeachers) {
                    if (Objects.equals(examTeacher.getExamRoomId(), examRommId) && Objects.equals(examTeacher.getIdentity(), "0")) {
                        list.add(examTeacher);
                    }
                }
                vo.setList(list);

            }
            /*如果该监考老师暂时未分配考场那么只显示该监考教师*/
        } else {
            if (!examTeachers.isEmpty()) {
                for (ExamTeacher examTeacher : examTeachers) {
                    boolean idEquals = Objects.equals(masterTearcher.getId(), examTeacher.getTeacherId());
                    boolean identityEquals = Objects.equals(examTeacher.getIdentity(), "0");
                    if (idEquals && identityEquals) {
                        list.add(examTeacher);
                    }
                }
                vo.setList(list);
            }
        }
        vo.getExam().setStudentNotes(null);
        return vo;
    }


    @Override
    public IPage<ExamStudent> findExamStudent(Integer id, Integer current, Integer size, Integer examRoomId) {
        AssertUtils.isNotNull(id, "考试id不可为空");
        AssertUtils.isNotNull(current, "当前页码不可为空");
        AssertUtils.isNotNull(size, "当前页码条数不可为空");
        AssertUtils.isNotNull(examRoomId, "当前考场id不可为空");
        IPage<ExamStudent> page = new Page<>(current, size);
        QueryWrapper<ExamStudent> wrapper = new QueryWrapper<>();
        wrapper.eq("exam_id", id)
                .eq("exam_room_id", examRoomId);
        page = examStudentMapper.selectPage(page, wrapper);
        return page;
    }

    @Override
    public ExamTeacher checkin(Integer id, HttpServletRequest request) {
        String userToken = request.getHeader(KwConstant.USERTOKEN);
        AssertUtils.isNotNull(id, "考试id不可为空");
        if (StringUtils.isNotBlank(userToken)) {
            String loginJson = RedisUtils.INSTANCE.get(userToken);
            MasterTearcher masterTearcher = JSON.parseObject(loginJson, MasterTearcher.class);
            if (masterTearcher != null && masterTearcher.getId() != null) {
                QueryWrapper<ExamTeacher> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("exam_id", id)
                        .eq("teacher_id", masterTearcher.getId());
                ExamTeacher examTeacher = examTeacherMapper.selectOne(queryWrapper);
                AssertUtils.isNotNull(examTeacher, "该监考老师无任何监考安排");
                examTeacher.setCheckinStatus("1")
                        .setCheckinTime(new Date())
                        .setUpdateTime(new Date());
                examTeacherMapper.updateById(examTeacher);
                return examTeacher;
            }
        }
        return null;
    }

    @Override
    public ExamTeacher checkinInfo(Integer id, HttpServletRequest request) {
        String userToken = request.getHeader(KwConstant.USERTOKEN);
        AssertUtils.isNotNull(id, "考试id不可为空");
        if (StringUtils.isNotBlank(userToken)) {
            String loginJson = RedisUtils.INSTANCE.get(userToken);
            MasterTearcher masterTearcher = JSON.parseObject(loginJson, MasterTearcher.class);
            if (masterTearcher != null && masterTearcher.getId() != null) {
                QueryWrapper<ExamTeacher> wrapper = new QueryWrapper<>();
                wrapper.eq("exam_id", id)
                        .eq("teacher_id", masterTearcher.getId());
                return examTeacherMapper.selectOne(wrapper);
            }
        }
        return null;
    }

    @Override
    public IPage<Exam> findNotInExam(PageDto dto, HttpServletRequest request) {
        IPage<Exam> page = new Page<>(dto.getCurrent(), dto.getSize());
        KwMasterTearcher masterTearcher = RedisUtils.INSTANCE.getLoginInfo(request.getHeader(KwConstant.USERTOKEN), KwMasterTearcher.class);
        QueryWrapper<ExamTeacher> examTeacherQueryWrapper = new QueryWrapper<>();
        examTeacherQueryWrapper.eq("teacher_id", masterTearcher.getId())
                .select("exam_id");
        /*查询出该监考老师的所有监考信息的考试id*/
        List<ExamTeacher> examTeachers = examTeacherMapper.selectList(examTeacherQueryWrapper);
        Set<Integer> examIds = new HashSet<>();
        for (ExamTeacher e : examTeachers) {
            if (e.getExamId() != null) {
                examIds.add(e.getExamId());
            }
        }
        /*如果该监考老师没有考试id，即未监考任何考试，查询全部考试*/
        if (examIds.isEmpty()) {
            page = examMapper.selectPage(page, null);
            return page;
        }
        /*如果该监考老师有监考，则查出未监考的考试*/
        QueryWrapper<Exam> examQueryWrapper = new QueryWrapper<>();
        examQueryWrapper.notIn("id", examIds);
        page = examMapper.selectPage(page, examQueryWrapper);

        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse enroll(Exam exam, HttpServletRequest request) {
        AssertUtils.isNotNull(exam, "考试信息不可为空");
        AssertUtils.isNotNull(exam.getId(), "考试id不可为空");
        KwMasterTearcher masterTearcher = RedisUtils.INSTANCE.getLoginInfo(request.getHeader(KwConstant.USERTOKEN), KwMasterTearcher.class);
        if (!masterTearcher.getIdentity().contains("0")) {
            return BaseResponse.failed("非监考教师不可报名");
        }
        if ("1".equals(exam.getStatus())) {
            return BaseResponse.failed("考试已结束");
        }
        /*查询该教师是否已经报名过这场考试*/
        QueryWrapper<ExamTeacher> examTeacherQueryWrapper = new QueryWrapper<>();
        examTeacherQueryWrapper.eq("exam_id", exam.getId())
                .eq("teacher_id", masterTearcher.getId());
        List<ExamTeacher> examTeachers = examTeacherMapper.selectList(examTeacherQueryWrapper);
        if (!examTeachers.isEmpty()) {
            return BaseResponse.failed("您已经报名过这场考试了");
        }

        /*查询出该教师的占用情况*/
        QueryWrapper<Occupy> wrapper = new QueryWrapper<>();
        wrapper.eq("type_id", masterTearcher.getId())
                .eq("type", "1");
        List<Occupy> list = occupyMapper.selectList(wrapper);
        if (!list.isEmpty()) {
            long examStartTime = exam.getStartTime().getTime();
            long examEndTime = exam.getEndTime().getTime();
            for (Occupy occupy : list) {
                long startTime = occupy.getStartTime().getTime();
                long endTime = occupy.getEndTime().getTime();
                /*如果传入的考试开始时间在表中的开始时间和结束时间之中则说明考试被占用*/
                if (examStartTime >= startTime && examStartTime <= endTime) {
                    return BaseResponse.failed("本次考试的开始时间在您的一场考试之间");
                }
                if (examEndTime >= startTime && examEndTime <= endTime) {
                    return BaseResponse.failed("本次考试的结束时间在您的一场考试之间");
                }
                if (startTime >= examStartTime && startTime <= examEndTime) {
                    return BaseResponse.failed("您有一场考试的开始时间在本次考试时间段之间");
                }
                if (endTime >= examStartTime && endTime <= examEndTime) {
                    return BaseResponse.failed("您有一场考试的结束时间在本次考试时间段之间");
                }
            }
        }
        Occupy occupy = new Occupy();
        occupy.setExamId(exam.getId())
                .setStartTime(exam.getStartTime())
                .setEndTime(exam.getEndTime())
                .setTypeId(masterTearcher.getId())
                .setType("1");
        occupyMapper.insert(occupy);
        ExamTeacher examTeacher = new ExamTeacher();
        BeanUtils.copyProperties(masterTearcher, examTeacher);
        examTeacher.setExamId(exam.getId())
                .setTeacherId(masterTearcher.getId())
                .setId(null);
        examTeacherMapper.insert(examTeacher);
        return BaseResponse.ok();
    }
}
